<?php
/**
 * Created by PhpStorm.
 * User: edmmss
 * Date: 2019-03-15
 * Time: 10:08
 */

namespace Edmmss\Crypt;

use yii\base\BaseObject;

class CryptAesOpenssl extends BaseObject
{
    const FIXED_IV = '04OfEgdVuX26DYvX';

    protected $cipher = 'aes-256-cbc';

    protected $iv = null;

    public function __construct($useFixedIv = false, array $config = [])
    {
        if ($useFixedIv) {
            $this->iv = self::FIXED_IV;
        }

        parent::__construct($config);
    }

    public function useFixedIv()
    {
        $this->iv = self::FIXED_IV;

        return $this;
    }

    public function setCipher($cipher)
    {
        if (!in_array($cipher, openssl_get_cipher_methods())) {
            throw new \Exception('no support cipher:' . $cipher);
        }
        $this->cipher = $cipher;

        return $this;
    }

    public function setIv($iv)
    {
        $this->iv = $iv;

        return $this;
    }

    public function encrypt($plaintext, $key)
    {
        $ivlen = openssl_cipher_iv_length($this->cipher);
        $this->iv = $this->iv ?: $this->getRandomIv($ivlen);
        $ciphertext = openssl_encrypt($plaintext, $this->cipher, $key, 0, $this->iv);

        $enText = rtrim(strtr(base64_encode($ciphertext), '+/', '-_'), '=');

        return $this->isUsingFixedIv() ? $enText : $this->iv . $enText;
    }

    public function decrypt($ciphertext, $key)
    {
        $ivlen = openssl_cipher_iv_length($this->cipher);
        if (!$this->isUsingFixedIv()) {
            $this->iv = substr($ciphertext, 0, $ivlen);
            $ciphertext = substr($ciphertext, $ivlen);
        }
        $str = base64_decode(str_pad(strtr($ciphertext, '-_', '+/'), strlen($ciphertext) % 4, '=', STR_PAD_RIGHT));
        $originalPlaintext = openssl_decrypt($str, $this->cipher, $key, 0, $this->iv);

        return $originalPlaintext;
    }

    private function isUsingFixedIv()
    {
        return $this->iv == self::FIXED_IV;
    }

    private function getRandomIv($length)
    {
        // 密码字符集，可任意添加你需要的字符
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $string = '';
        for ($i = 0; $i < $length; $i++) {
            $string .= $chars[mt_rand(0, strlen($chars) - 1)];
        }

        return $string;
    }
}